/*!
 * \file frdb_cursor.h
 *
 * \brief DB共通处理
 *
 * All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.\n
 * Cursor做成,更新，删除，数据上报等操作
 *
 * \version 2.0
 * \author zhengxd
 * \date 2014/12/17
 *
 */

#ifndef __FRDB_CURSOR_H_
#define __FRDB_CURSOR_H_

#include "frcomm.h"
#include "frhash2.h"
#include "frlog.h"

#include "conntrack.h"
#include "module.h"
#include "frreport_comm.h"

#define FRDB_LAST                        0
#define FRDB_SPECIFIED                   1

#define FRDB_BIND                        0
#define FRDB_COLUMN                      1
#define FRDB_DEFINE                      2
#define FRDB_CHG_WORD                    '?'

#define FRDB_REPORT_KEY_REQ_TEXT               APM_REPORT_KEY_REQ".sql.text"
#define FRDB_REPORT_KEY_REQ_SQL_BATCH_SIZE     APM_REPORT_KEY_REQ".sql.batch.size"
#define FRDB_REPORT_KEY_REQ_SQL_BATCH          APM_REPORT_KEY_REQ".sql.batch"
#define FRDB_REPORT_KEY_RESP_SQL_BATCH         APM_REPORT_KEY_RESP".sql.batch"

/*! @brief 请求和应答相关的时间、数据长度 */
typedef struct __st_sql_req_resp_info {

    struct timeval st_request_start_time;     /*!< 请求发起的第一个数据包时间 */
    struct timeval st_request_end_time;       /*!< 所有请求数据发送完的时间 */
    unsigned long ul_send_time_us;           /*!< 请求发送时间(单位usec) */
    unsigned long ul_request_bytes;          /*!< 请求字节数，in bytes */

    struct timeval st_response_start_time;    /*!< 收到第一个应答包时间 */
    struct timeval st_response_end_time;      /*!< 所有应答包数据接收完的时间 */
    unsigned long ul_server_time_us;         /*!< 服务器运行时间(单位usec) */
    unsigned long ul_download_time_us;       /*!< 下载时间(单位usec) */
    unsigned long ul_response_bytes;          /*!< 应答的字节数， in bytes */
} Sql_req_resp_info;

/*! @brief metadata信息 */
typedef struct __st_sql_metadata_info
{
    int i_data_type;              /*!< 数据类型 */
    unsigned int ui_len;         /*!< 数据长度 */
    unsigned int ui_precision;   /*!< precision */
    unsigned int ui_scale;       /*!< scale */
    int i_status;                 /*!< status */
    int i_isuseless;             /*!< 该字段是否是无用的 */
    int i_isnullbydescribe;      /*!< 该字段是否是由描述定义的null类型 */
    int i_mssql_plp_flg;         /*!< MSSQL是否属于PLP */

    short s_ora_oacdty;
    short s_ora_oacflg;            /*!< Oracle oacflg */
    short s_ora_oacpre;
    short s_ora_oacscl;
    int i_ora_oacmxl;
    int i_ora_oacmal;
    int i_ora_oacfl2;
    int i_ora_oacvsn;
    int i_ora_oaccsi;
    short s_ora_oaccsfrm;
    int i_ora_oacmxlc;
    int i_ora_dml_returned_param;
} Sql_metadata_info;

/*! @brief Bind信息 */
typedef struct __st_sql_field_bind
{
    Frlist_header st_field_list;       /*!< 数据(Frdata_field *) */
} Sql_field_bind;

/*! @brief 请求响应的结果集信息 */
typedef struct __st_sql_resultset
{
    int i_req_report;                  /*!< request是否上报标识 */
    long l_id;                         /*!< ID */
    unsigned long ul_req_sequence;    /*!< 请求序列号 */
    Frlist_header st_bind_list;        /*!< 数据(Sql_field_bind *) */
    Sql_req_resp_info st_req_resp;     /*!< 请求响应信息 */
    unsigned int ui_response_count;   /*!< 响应个数(batch情况有多个返回值) */
    unsigned long *p_ul_rows;         /*!< 影响到的行数(batch情况有多个返回值) */
} Sql_resultset;

/*! @brief Statement信息 */
typedef struct __st_sql_statement
{
    long l_cursor_id;                 /*!< cursor id */
    char *p_sql;                      /*!< SQL语句 */
    int i_is_dml;                     /*!< isDML(ORACLE独有) */
    long long ll_ora_options;
    int i_is_first;                   /*!< 是否是第一次bind */
    int i_column_nums;                /*!< 列数 */
    Frlist_header st_metadata_bind;    /*!< bind的metadata(Sql_metadata_info *) */
    Frlist_header st_metadata_column;  /*!< column的metadata(Sql_metadata_info *) */
    Frlist_header st_metadata_define;  /*!< define的metadata(Sql_metadata_info *) */
    Frlist_header st_resultset_list;   /*!< 结果集列表(Sql_resultset *) */
} Sql_statement;

/*!
 * 替换title里边的值
 *
 * \param p_org_title         (源title)
 * \param c_chg_word          (转换用字符)
 * \param pp_result_title     (转换后title)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 * \note 规则：[,后的数值][=后的数值][''之间的字符]全部替换成要替换字符
 *
 */
int frdb_title_value_chg(char *p_org_title
                         , char c_chg_word
                         , char **pp_result_title);

/*!
 * Metadata结构体释放
 *
 * \param pp_st_metadata      (Sql_metadata_info**)
 *
 */
void frdb_metadata_free(Sql_metadata_info **pp_st_metadata);

/*!
 * Metadata节点释放函数指针
 *
 * \param p_st_node      (Frlist_node*)
 *
 */
void frdb_metadata_node_free(Frlist_node *p_st_node);

/*!
 * 追加metadata到statement
 *
 * \param p_st_statement    (Statement)
 * \param i_type            (FRDB_BIND/FRDB_COLUMN/FRDB_DEFINE)
 * \param p_st_metadata     (metadata信息)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 */
int frdb_add_metadata_info(Sql_statement *p_st_statement
                          , int i_type
                          , Sql_metadata_info *p_st_metadata);

/*!
 * 取得statement里的第一个metadata节点
 *
 * \param p_st_statement      (Statement)
 * \param i_type              (FRDB_BIND/FRDB_COLUMN/FRDB_DEFINE)
 *
 * \return 成功时返回节点, 否则返回NULL
 *
 */
Frlist_node* frdb_get_first_metadata(Sql_statement *p_st_statement
                                    , int i_type);

/*!
 * 取得statement里的指定metadata节点
 *
 * \param p_st_statement      (Statement)
 * \param i_type              (FRDB_BIND/FRDB_COLUMN/FRDB_DEFINE)
 * \param i_index             (要取的节点位置)
 *
 * \return 成功时返回节点, 否则返回NULL
 *
 */
Sql_metadata_info* frdb_get_specified_metadata(Sql_statement *p_st_statement
                                              , int i_type
                                              , int i_index);

/*!
 * Bind结构体释放
 *
 * \param pp_st_data      (Sql_field_bind**)
 *
 */
void frdb_field_bind_free(Sql_field_bind **pp_st_data);

/*!
 * Bind节点释放函数指针
 *
 * \param p_st_node      (Frlist_node*)
 *
 */
void frdb_field_bind_node_free(Frlist_node *p_st_node);

/*!
 * Frlist_header的深度拷贝
 *
 * \param p_lst_dest         (目标(Frdata_field *)链表)
 * \param p_lst_source       (源数(Frdata_field *)链表)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 * \note p_lst_dest和p_lst_source都必须不为NULL
 *
 */
int frdb_frlist_copy(Frlist_header *p_lst_dest, Frlist_header *p_lst_source);

/*!
 * 结果集结构体释放
 *
 * \param pp_st_data      (Sql_resultset**)
 *
 */
void frdb_resultset_free(Sql_resultset **pp_st_resultset);

/*!
 * 结果集节点释放函数指针
 *
 * \param p_st_node      (Frlist_node*)
 *
 */
void frdb_resultset_node_free(Frlist_node *p_st_node);

/*!
 * Statement结构体释放
 *
 * \param pp_st_data      (Sql_statement**)
 *
 */
void frdb_statement_free(Sql_statement **pp_st_statement);

/*!
 * Statement节点释放函数指针
 *
 * \param p_st_node      (Frlist_node*)
 *
 */
void frdb_statement_node_free(Frlist_node *p_st_node);

/*!
 * 创建Statement结构体
 *
 * \return 成功时返回Statement, 否则返回NULL
 *
 */
Sql_statement* frdb_create_statement();

/*!
 * 判定是不是statement的第一次使用结果集
 *
 * \param p_st_statement     (Sql_statement *)
 *
 * \return 0:NO\n
 *         1:YES
 *
 */
int frdb_is_first_result(Sql_statement *p_st_statement);

/*!
 * 设置当前的statement的结果集已经被使用过
 *
 * \param p_st_statement     (Sql_statement *)
 *
 */
void frdb_statement_used(Sql_statement *p_st_statement);

/*!
 * 追加参数列表到结果集
 *
 * \param p_st_resultset         (结果集)
 * \param p_st_bind              (Bind参数)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 */
int frdb_add_resultset_bind(Sql_resultset *p_st_resultset
                            , Sql_field_bind *p_st_bind);

/*!
 * 设置sql语句
 *
 * \param p_st_statement     (Statement)
 * \param p_sql              (sql语句)
 *
 */
void frdb_set_sql(Sql_statement *p_st_statement, char *p_sql);

/*!
 * 重置sql语句
 *
 * \param p_st_statement     (Statement)
 * \param p_sql              (sql语句)
 *
 */
void frdb_reset_sql(Sql_statement *p_st_statement, char *p_sql);

/*!
 * 创建结果集
 *
 * \param ul_req_sequence         (请求序列号)
 *
 * \note 成功时返回结果集, 否则返回NULL
 *
 */
Sql_resultset* frdb_create_resultset(unsigned long ul_req_sequence);

/*!
 * 追加结果集到statement
 *
 * \param p_st_statement         (Statement)
 * \param p_st_resultset         (结果集)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 */
int frdb_add_resultset(Sql_statement *p_st_statement
                      , Sql_resultset *p_st_resultset);

/*!
 * 初始化结果集
 *
 * \param p_st_resultset         (结果集)
 * \param ul_req_sequence        (请求序列号)
 *
 */
void frdb_init_resultset(Sql_resultset *p_st_resultset
                        , unsigned long ul_req_sequence);

/*!
 * 取得statement里的最后一个结果集
 *
 * \param p_st_statement         (Statement)
 *
 * \return 成功时返回结果集, 否则返回NULL
 *
 */
Sql_resultset* frdb_get_last_resultset(Sql_statement *p_st_statement);

/*!
 * 删除statement里的第一个结果集
 *
 * \param p_st_statement         (Statement)
 *
 */
void frdb_del_first_resultset(Sql_statement *p_st_statement);

/*!
 * 删除statement里的最后一个结果集
 *
 * \param p_st_statement         (Statement)
 *
 */
void frdb_del_last_resultset(Sql_statement *p_st_statement);

/*!
 * 删除对应sequence id的结果集
 *
 * \param p_st_statement         (Statement)
 * \param l_sequence_id          (sequence id)
 *
 */
void frdb_del_specified_resultset(Sql_statement *p_st_statement
                                  , long l_sequence_id);

/*!
 * 取得对应sequence id的结果集
 *
 * \param p_st_statement         (Statement)
 * \param l_sequence_id          (sequence id)
 *
 * \return 成功时返回结果集, 否则返回NULL
 *
 */
Sql_resultset* frdb_get_specified_resultset(Sql_statement *p_st_statement
                                            , long l_sequence_id);

/*!
 * 设置结果集的request信息
 *
 * \param p_st_resultset           (结果集)
 * \param ul_request_bytes         (当前request的字节数)
 * \param p_st_request_start_time  (当前request的首包时间)
 * \param p_st_request_end_time    (当前request的末包时间)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 */
int frdb_set_resultset_req2(Sql_resultset *p_st_resultset
                            , unsigned long ul_request_bytes
                            , struct timeval *p_st_request_start_time
                            , struct timeval *p_st_request_end_time);

/*!
 * 设置结果集的response信息
 *
 * \param p_st_resultset             (结果集)
 * \param ul_response_bytes          (当前response的字节数)
 * \param ui_response_count          (响应个数)
 * \param p_ul_effect_rows           (具体响应值)
 * \param p_st_response_start_time   (当前response的首包时间)
 * \param p_st_response_end_time     (当前response的末包时间)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 * \note p_ll_effect_rows为NULL时表示该响应的effect rows将被忽略
 *
 */
int frdb_set_resultset_resp2(Sql_resultset *p_st_resultset
                            , unsigned long ul_response_bytes
                            , unsigned int ui_response_count
                            , unsigned long *p_ul_effect_rows
                            , struct timeval *p_st_response_start_time
                            , struct timeval *p_st_response_end_time);

/*!
 * 设置结果集的request信息
 *
 * \param p_st_statement           (Statement)
 * \param i_flg                    (FRDB_LAST/FRDB_SPECIFIED)
 * \param l_sequence_id            (sequence id)
 * \param ul_request_bytes         (当前request的字节数)
 * \param p_st_request_start_time  (当前request的首包时间)
 * \param p_st_request_end_time    (当前request的末包时间)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 */
int frdb_set_resultset_req(Sql_statement *p_st_statement
                          , int i_flg
                          , long l_sequence_id
                          , unsigned long ul_request_bytes
                          , struct timeval *p_st_request_start_time
                          , struct timeval *p_st_request_end_time);

/*!
 * 设置结果集的response信息
 *
 * \param p_st_statement             (Statement)
 * \param i_flg                      (FRDB_LAST/FRDB_SPECIFIED)
 * \param l_sequence_id              (sequence id)
 * \param ul_response_bytes          (当前response的字节数)
 * \param ui_response_count          (响应个数)
 * \param p_ul_effect_rows           (具体响应值)
 * \param p_st_response_start_time   (当前response的首包时间)
 * \param p_st_response_end_time     (当前response的末包时间)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 * \note p_ll_effect_rows为NULL时表示该响应的effect rows将被忽略
 *
 */
int frdb_set_resultset_resp(Sql_statement *p_st_statement
                            , int i_flg
                            , long l_sequence_id
                            , unsigned long ul_response_bytes
                            , unsigned int ui_response_count
                            , unsigned long *p_ul_effect_rows
                            , struct timeval *p_st_response_start_time
                            , struct timeval *p_st_response_end_time);

/*!
 * 上报request信息
 *
 * \param p_st_conn          (CT信息)
 * \param p_st_hash_report   (report hash)
 * \param p_st_statement     (statement信息)
 * \param p_st_resultset     (结果集信息)
 * \param pp_st_body_session (session信息)
 * \param pp_st_body_req     (request report body)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 * \note pp_st_body_session必须创建，设置除了title之外的所有自定义数据
 *
 */
int frdb_report_req2(Conntrack *p_st_conn
                    , Frhash_header *p_st_hash_report
                    , Sql_statement *p_st_statement
                    , Sql_resultset *p_st_resultset
                    , Frreport_body_data **pp_st_body_session);

/*!
 * 上报response信息
 *
 * \param p_st_conn          (CT信息)
 * \param p_st_hash_report   (report hash)
 * \param p_st_statement     (statement信息)
 * \param p_st_resultset     (结果集信息)
 * \param l_resp_code        (response code)
 * \param p_error_code       (error code string)
 * \param p_error_msg        (error message)
 * \param pp_st_body_session (session信息)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 * \note pp_st_body_session必须创建，设置除了title之外的所有自定义数据
 *
 */
int frdb_report_resp2(Conntrack *p_st_conn
                     , Frhash_header *p_st_hash_report
                     , Sql_statement *p_st_statement
                     , Sql_resultset *p_st_resultset
                     , long l_resp_code
                     , char *p_error_code
                     , char *p_error_msg
                     , Frreport_body_data **pp_st_body_session);

/*!
 * 上报request信息
 *
 * \param p_st_conn          (CT信息)
 * \param p_st_hash_report   (report hash)
 * \param p_st_statement     (statement信息)
 * \param i_flg              (FRDB_LAST/FRDB_SPECIFIED)
 * \param l_sequence_id      (sequence id)
 * \param pp_st_body_session (session信息)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 * \note pp_st_body_session必须创建，设置除了title之外的所有自定义数据
 *
 */
int frdb_report_req(Conntrack *p_st_conn
                   , Frhash_header *p_st_hash_report
                   , Sql_statement *p_st_statement
                   , int i_flg
                   , long l_sequence_id
                   , Frreport_body_data **pp_st_body_session);

/*!
 * 上报response信息
 *
 * \param p_st_conn          (CT信息)
 * \param p_st_hash_report   (report hash)
 * \param p_st_statement     (statement信息)
 * \param i_flg              (FRDB_LAST/FRDB_SPECIFIED)
 * \param l_sequence_id      (sequence id)
 * \param l_resp_code        (response code)
 * \param p_error_code        (error code string)
 * \param p_error_msg        (error message)
 * \param pp_st_body_session (session信息)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 * \note pp_st_body_session必须创建，设置除了title之外的所有自定义数据
 *
 */
int frdb_report_resp(Conntrack *p_st_conn
                    , Frhash_header *p_st_hash_report
                    , Sql_statement *p_st_statement
                    , int i_flg
                    , long l_sequence_id
                    , long l_resp_code
                    , char *p_error_code
                    , char *p_error_msg
                    , Frreport_body_data **pp_st_body_session);

/*!
 * 将做成的statement追加到hash
 *
 * \param p_hash_statement   (hash头结点)
 * \param l_cursor_id        (cursor ID)
 * \param p_st_statement     (statement信息)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 */
int frdb_add_statement(Frhash_header *p_hash_statement
                       , long l_cursor_id
                       , Sql_statement *p_st_statement);

/*!
 * 从hash中取出指定statement
 *
 * \param p_hash_header      (hash头结点)
 * \param l_cursor_id        (cursor ID)
 *
 * \return 成功时返回Statement, 否则返回NULL
 *
 */
Sql_statement* frdb_get_statement(Frhash_header *p_hash_header
                                  , long l_cursor_id);

/*!
 * 设置序列号
 *
 * \param p_st_statement     (Statement信息)
 * \param i_flg              (FRDB_LAST/FRDB_SPECIFIED)
 * \param l_sequence_id      (sequence id)
 * \param ul_req_sequence    (请求序列号)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 */
int frdb_set_req_sequence(Sql_statement *p_st_statement
                          , int i_flg
                          , long l_sequence_id
                          , unsigned long ul_req_sequence);

/*!
 * 设置序列号
 *
 * \param p_st_resultset     (结果集信息)
 * \param ul_req_sequence    (请求序列号)
 *
 */
void frdb_set_req_sequence2(Sql_resultset *p_st_resultset
                            , unsigned long ul_req_sequence);

/*!
 * 取得resultset序列号
 *
 * \param p_st_statement     (Statement信息)
 * \param l_sequence_id      (sequence id)
 * \param ul_req_sequence    (请求序列号)
 *
 * \return 序列号
 *
 */
unsigned long frdb_get_req_sequence(Sql_statement *p_st_statement
                                      , int i_flg
                                      , long l_sequence_id);

/*!
 * 取得resultset序列号
 *
 * \param p_st_resultset     (结果集信息)
 *
 * \return 序列号
 *
 */
unsigned long frdb_get_req_sequence2(Sql_resultset *p_st_resultset);

/*!
 * 设置列数
 *
 * \param p_st_statement         (Statement信息)
 * \param i_column_nums          (列数)
 *
 * \note p_st_statement不能为NULL
 *
 */
void frdb_set_column_nums(Sql_statement *p_st_statement, int i_column_nums);

/*!
 * 取得列数
 *
 * \param p_st_statement     (Statement信息)
 *
 * \return 列数
 *
 */
int frdb_get_column_nums(Sql_statement *p_st_statement);

#endif
